#pragma once
//============================================================================
// Copyright (C) 2013 Brett R. Jones
//
// Issued to public domain 2013
//
// brettjones1900@gmail.com
// http://www.p2panarchy.com
//============================================================================
#include <string>
#include <vector>
#include "VxDefs.h"

#ifndef WIN_PLATFORM
    #include <netdb.h>        /* getaddrinfo(3) et al.                       */
    #include <netinet/in.h>   /* sockaddr_in & sockaddr_in6 definition.      */
	#include <unistd.h> 
#endif // WIN_PLATFORM

#pragma pack(push) 
#pragma pack(1)
class VxInetAddress
{
public:
	//=== vars ===//
	U64 m_u64AddrHi;
	U64 m_u64AddrLo;

	VxInetAddress();
	
	VxInetAddress( const char * pIpAddress );
	VxInetAddress( U32 u32IpAddr );

    VxInetAddress& operator=(const VxInetAddress& oAddr);
    bool operator != (const VxInetAddress& oAddr) const;
    bool operator == (const VxInetAddress& oAddr) const;

    bool                    runTests();

	//=== methods ===//
    bool                    isValid( void );
    void                    setToInvalid( void );
    bool                    isIPv4( void );
    bool                    isIPv6( void );
    bool                    isIPv6GlobalAddress( void );
    bool                    isLoopBack( void );

    void                    setIp( const char * pIpAddress );
	// note.. u32IPv4Addr must be in host order
    void                    setIp( U32 u32IPv4Addr, bool bIsHostOrder = false );
	//! returns port in host order
    U16                     setIp( struct sockaddr_storage& oAddr );

	
	//! fill address with this ip address and the given port.. returns struct len
    int                     fillAddress( struct sockaddr_storage& oAddr, U16 port );

    void                    toStdString( std::string& retIpAddress );
    std::string             toStdString( void );

	// get ip in host order
    U32                     getIPv4AddressInHostOrder( void );
	// get ip in network order (little endian)
    U32                     getIPv4AddressInNetOrder( void );
	//! returns port in host order
	static U16				getIpFromAddr(const struct sockaddr *sa, std::string& retStr);
	static VxInetAddress    getDefaultIp( void );
    static int				getAllAddresses( std::vector<VxInetAddress>& retAddress );

private:
	//! returns port in host order
    U16                     setIp( struct sockaddr_in& oIPv4Addr );
	//! returns port in host order
    U16                     setIp( struct sockaddr_in6& oIPv6Addr );
	//! fill address with this ip address and the given port.. returns struct len
    int                     fillAddress( struct sockaddr_in& oIPv4Addr, U16 port );
	//! fill address with this ip address and the given port.. returns struct len
    int                     fillAddress( struct sockaddr_in6& oIPv6Addr, U16 port );

    bool                    isIPv4String( const char * pIpAddress );
	// set ip from string
    void                    fromString( const char * pIpAddress );

    bool                    isLittleEndian( void );
    bool                    is64BitLittleEndianOs( void );
    void                    litteEndianToNetIPv6( U16 * src, U16 * dest);
    U64                     swap64Bit( U64 src );

};

class VxInetAddrAndPort : public VxInetAddress
{
public:
    U16                     m_u16Port;

    VxInetAddrAndPort();

    U16                     getPort( void )				{ return m_u16Port; }
    void                    setPort( U16 u16Port )		{ m_u16Port = u16Port; }

    void                    setIpAndPort( struct sockaddr_storage& oAddr );

    VxInetAddrAndPort& operator=(const VxInetAddress& oAddr);
    VxInetAddrAndPort& operator=(const VxInetAddrAndPort& oAddr);

};

#pragma pack(pop)
